package com.uzai.console.common.utils;

import com.taobao.api.internal.toplink.embedded.websocket.util.StringUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 表情工具类
 * @author liuqi
 * @date 2022年08月08日 10:40
 */
public class EmojiUtil {
    /**
     * 将带表情的文本转换为特殊格式的文本
     *
     * @param source
     * @return
     */
    public static StringBuffer emojiText2Text(String source) {
        StringBuffer buffer = new StringBuffer();// 转换以后的文本
        int length = source.length();
        int skip;
        for (int i = 0; i < length; i += skip) {
            skip = 0;
            boolean bSoftBankEmoji = false;
            char c = source.charAt(i);
            if (isSoftBankEmoji(c)) {// 是否是SoftBankEmoji表情码
                bSoftBankEmoji = true;
                skip = 1;
            }
            String unicodeHexStr = "";
            if (!bSoftBankEmoji) {
                int unicode = Character.codePointAt(source, i);// 把text中的索引位置开始的那个表情转换成16进制码
                unicodeHexStr = Integer.toHexString(unicode);
                System.out.println(Integer.toHexString(unicode) + "---16");// 这个就是0x1f603，表情的16进制
                skip = Character.charCount(unicode);// 计算出表情站位多少，应该是2
                boolean bunicode = unicode > 0xff;

                if (!bunicode && i + skip < length) {
                    int followUnicode = Character.codePointAt(source, i + skip);
                    if (followUnicode == 0x20e3) {
                        int followSkip = Character.charCount(followUnicode);
                        switch (unicode) {
                            case 0x0031:
                            case 0x0032:
                            case 0x0033:
                            case 0x0034:
                            case 0x0035:
                            case 0x0036:
                            case 0x0037:
                            case 0x0038:
                            case 0x0039:
                            case 0x0030:
                            case 0x0023:
                                break;
                            default:
                                followSkip = 0;
                                break;
                        }
                        skip += followSkip;
                    } else {
                        int followSkip = Character.charCount(followUnicode);
                        switch (unicode) {
                            case 0x1f1ef:
                                bunicode = followUnicode == 0x1f1f5;
                                break;
                            case 0x1f1fa:
                                bunicode = followUnicode == 0x1f1f8;
                                break;
                            case 0x1f1eb:
                                bunicode = followUnicode == 0x1f1f7;
                                break;
                            case 0x1f1e9:
                                bunicode = followUnicode == 0x1f1ea;
                                break;
                            case 0x1f1ee:
                                bunicode = followUnicode == 0x1f1f9;
                                break;
                            case 0x1f1ec:
                                bunicode = followUnicode == 0x1f1e7;
                                break;
                            case 0x1f1ea:
                                bunicode = followUnicode == 0x1f1f8;
                                break;
                            case 0x1f1f7:
                                bunicode = followUnicode == 0x1f1fa;
                                break;
                            case 0x1f1e8:
                                bunicode = followUnicode == 0x1f1f3;
                                break;
                            case 0x1f1f0:
                                bunicode = followUnicode == 0x1f1f7;
                                break;
                            default:
                                followSkip = 0;
                                break;
                        }
                        skip += followSkip;
                    }
                }
            }
            if (skip == 2) {// 是表情
                buffer.append("#0x"
                        + unicodeHexStr + "#");
            } else {
                buffer.append(source.substring(i, i + skip));
            }
            System.out.println(buffer.toString());
        }
        return buffer;
    }

    // 把特殊格式的文本转成带表情的文本
    public static String text2EmojiText(String st) {
        Pattern pattern = Pattern.compile("#0x.+?#", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(st);
        StringBuffer buffer = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(buffer, emoji2Unicode(matcher.group()
                    .replace("#", "")));
        }
        matcher.appendTail(buffer);

        return buffer.toString();
    }

    private static boolean isSoftBankEmoji(char c) {
        return ((c >> 12) == 0xe);
    }

    // high offset
    public static final int W1 = Integer.valueOf("D7C0", 16);

    // low offset
    public static final int W2 = Integer.valueOf("DC00", 16);

    // 表情转Unicode
    public static String emoji2Unicode(String ed) {
        String doughnutBinary = Integer.toBinaryString(Integer.valueOf(
                ed.substring(2), 16));
        // 拆成高低 10 位表示
        String highSetsBinary = doughnutBinary.substring(0,
                doughnutBinary.length() - 10);
        String lowSetsBinary = doughnutBinary.substring(
                doughnutBinary.length() - 10, doughnutBinary.length());
        System.out.println(highSetsBinary); // 1111100
        System.out.println(lowSetsBinary); // 1100000000

        // 分别与偏移量相加，得到两个编码值
        String highSetsHexFixed = Integer.toHexString(W1
                + Integer.valueOf(highSetsBinary, 2));
        String lowSetsHexFixed = Integer.toHexString(W2
                + Integer.valueOf(lowSetsBinary, 2));
        System.out.println(highSetsHexFixed); // d83c
        System.out.println(lowSetsHexFixed); // df00

        // 拼接这两个编码值，还原字符表示
        char highChar = (char) Integer.valueOf(highSetsHexFixed, 16).intValue();
        char lowChar = (char) Integer.valueOf(lowSetsHexFixed, 16).intValue();
        System.out.println(highChar); // ?
        System.out.println(lowChar); // ?
        System.out.println(highChar + "" + lowChar); // 🌀
        // mTxtEmojicon.setText(highChar + "" + lowChar);
        return highChar + "" + lowChar;
    }

    // Unicode 转表情
    public static String unicode2Emoji(String ss) {
        return (Integer
                .toHexString(Integer.valueOf(
                        Integer.toBinaryString((Integer.parseInt(
                                Integer.toHexString(ss.toCharArray()[0]), 16) - W1))
                                + Integer.toBinaryString((Integer.parseInt(
                                Integer.toHexString(ss.toCharArray()[1]),
                                16) - W2)), 2))).toLowerCase();
    }

    /**
     * 判断字符串中是否含有表情
     * @param source
     * @return
     */
    public static boolean containsEmoji(String source) {

        if(StringUtils.isBlank(source)){
            return false;
        }

        boolean isEmoji = false;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char hs = source.charAt(i);
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (source.length() > 1) {
                    char ls = source.charAt(i + 1);
                    int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        return true;
                    }
                }
            } else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
                    return true;
                } else if (0x2B05 <= hs && hs <= 0x2b07) {
                    return true;
                } else if (0x2934 <= hs && hs <= 0x2935) {
                    return true;
                } else if (0x3297 <= hs && hs <= 0x3299) {
                    return true;
                } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d
                        || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c
                        || hs == 0x2b1b || hs == 0x2b50 || hs == 0x231a) {
                    return true;
                }
                if (!isEmoji && source.length() > 1 && i < source.length() - 1) {
                    char ls = source.charAt(i + 1);
                    if (ls == 0x20e3) {
                        return true;
                    }
                }
            }
        }
        return isEmoji;
    }

    /**
     * 判断某个字符是不是表情
     * @param codePoint
     * @return
     */
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    /**
     * 过滤掉字符串中的表情
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return source;
        }
        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (isEmojiCharacter(codePoint)) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            return source;
        } else {
            if (buf.length() == len) {
                buf = null;
                return source;
            } else {
                return buf.toString();
            }
        }
    }

    private static final List<String> EMOJIS = Arrays.asList(
            "🧧","😎","😍","🌹","🌻","👉","👏","🌷","👍","🌹",
            "✨","📢","🔔","💡","🎁","🎉","🌻","🌛","💰","❤️",
            "🍀","🔥","🎈","🌴","🍉","🙆","🏃","🌈","🌸","😸",
            "😺","🎁","💐","😝","❤️","🌼","🌹","😛","🌱","🌾",
            "🚌","🍒","🌻","🌄","🌻","💥","📣","👑","🌹","💐",
            "🍎","🎁","🍰","👯","🍣","😁","🎁","😻","🍤","💫",
            "🌟","😘","🍓","🌻","🌺","💕","🌜","🙋","🌹","👌"
    );

    public static String getRandomEmoji(){
        return EMOJIS.get(CommonUtil.random(0, EMOJIS.size()));
    }

    public static void main(String[] args){
        System.out.println(getRandomEmoji());
    }
}
